home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Interactive Reference Guide
/
C-C++ Interactive Reference Guide.iso
/
c_ref
/
csource3
/
198_01
/
basic.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-01-23
|
17KB
|
626 lines
/*
* The routines in this file move the cursor around on the screen. They
* compute a new value for the cursor, then adjust ".". The display code
* always updates the cursor location, so only moves between lines, or
* functions that adjust the top line in the window and invalidate the
* framing, are hard.
*/
#include <stdio.h>
#include "estruct.h"
#include "edef.h"
/*
* Move the cursor to the
* beginning of the current line.
* Trivial.
*/
gobol(f, n)
{
curwp->w_doto = 0;
return (TRUE);
}
/*
* Move the cursor backwards by "n" characters. If "n" is less than zero call
* "forwchar" to actually do the move. Otherwise compute the new cursor
* location. Error if you try and move out of the buffer. Set the flag if the
* line pointer for dot changes.
*/
backchar(f, n)
register int n;
{
register LINE *lp;
if (n < 0)
return (forwchar(f, -n));
while (n--) {
if (curwp->w_doto == 0) {
if ((lp=lback(curwp->w_dotp)) == curbp->b_linep)
return (FALSE);
curwp->w_dotp = lp;
curwp->w_doto = llength(lp);
curwp->w_flag |= WFMOVE;
} else
curwp->w_doto--;
}
return (TRUE);
}
/*
* Move the cursor to the end of the current line. Trivial. No errors.
*/
goeol(f, n)
{
curwp->w_doto = llength(curwp->w_dotp);
return (TRUE);
}
/*
* Move the cursor forwards by "n" characters. If "n" is less than zero call
* "backchar" to actually do the move. Otherwise compute the new cursor
* location, and move ".". Error if you try and move off the end of the
* buffer. Set the flag if the line pointer for dot changes.
*/
forwchar(f, n)
register int n;
{
if (n < 0)
return (backchar(f, -n));
while (n--) {
if (curwp->w_doto == llength(curwp->w_dotp)) {
if (curwp->w_dotp == curbp->b_linep)
return (FALSE);
curwp->w_dotp = lforw(curwp->w_dotp);
curwp->w_doto = 0;
curwp->w_flag |= WFMOVE;
} else
curwp->w_doto++;
}
return (TRUE);
}
gotoline(f, n) /* move to a particular line.
argument (n) must be a positive integer for
this to actually do anything */
{
register int status; /* status return */
char arg[NSTRING]; /* buffer to hold argument */
/* get an argument if one doesnt exist */
if (f == FALSE) {
if ((status=mlreply("Line to GOTO: ", arg, NSTRING)) != TRUE) {
mlwrite("[Aborted]");
return(status);
}
n = atoi(arg);
}
if (n < 1) /* if a bogus argument...then leave */
return(FALSE);
/* first, we go to the start of the buffer */
curwp->w_dotp = lforw(curbp->b_linep);
curwp->w_doto = 0;
return(forwline(f, n-1));
}
/*
* Goto the beginning of the buffer. Massive adjustment of dot. This is
* considered to be hard motion; it really isn't if the original value of dot
* is the same as the new value of dot. Normally bound to "M-<".
*/
gobob(f, n)
{
curwp->w_dotp = lforw(curbp->b_linep);
curwp->w_doto = 0;
curwp->w_flag |= WFHARD;
return (TRUE);
}
/*
* Move to the end of the buffer. Dot is always put at the end of the file
* (ZJ). The standard screen code does most of the hard parts of update.
* Bound to "M->".
*/
goeob(f, n)
{
curwp->w_dotp = curbp->b_linep;
curwp->w_doto = 0;
curwp->w_flag |= WFHARD;
return (TRUE);
}
/*
* Move forward by full lines. If the number of lines to move is less than
* zero, call the backward line function to actually do it. The last command
* controls how the goal column is set. Bound to "C-N". No errors are
* possible.
*/
forwline(f, n)
{
register LINE *dlp;
if (n < 0)
return (backline(f, -n));
/* flag this command as a line move */
thisflag |= CFCPCN;
/* if we are on the last line as we start....fail the command */
if (curwp->w_dotp == curbp->b_linep)
return(FALSE);
/* if the last command was not note a line move,
reset the goal column */
if ((lastflag&CFCPCN) == 0)
curgoal = getccol(FALSE);
/* and move the point down */
dlp = curwp->w_dotp;
while (n-- && dlp!=curbp->b_linep)
dlp = lforw(dlp);
/* reseting the current position */
curwp->w_dotp = dlp;
curwp->w_doto = getgoal(dlp);
curwp->w_flag |= WFMOVE;
return (TRUE);
}
/*
* This function is like "forwline", but goes backwards. The scheme is exactly
* the same. Check for arguments that are less than zero and call your
* alternate. Figure out the new line and call "movedot" to perform the
* motion. No errors are possible. Bound to "C-P".
*/
backline(f, n)
{
register LINE *dlp;
if (n < 0)
return (forwline(f, -n));
/* flag this command as a line move */
thisflag |= CFCPCN;
/* if we are on the last line as we start....fail the command */
if (lback(curwp->w_dotp) == curbp->b_linep)
return(FALSE);
/* if the last command was not note a line move,
reset the goal column */
if ((lastflag&CFCPCN) == 0)
curgoal = getccol(FALSE);
/* and move the point up */
dlp = curwp->w_dotp;
while (n-- && lback(dlp)!=curbp->b_linep)
dlp = lback(dlp);
/* reseting the current position */
curwp->w_dotp = dlp;
curwp->w_doto = getgoal(dlp);
curwp->w_flag |= WFMOVE;
return (TRUE);
}
#if WORDPRO
gobop(f, n) /* go back to the beginning of the current paragraph
here we look for a <NL><NL> or <NL><TAB> or <NL><SPACE>
combination to delimit the beginning of a paragraph */
int f, n; /* default Flag & Numeric argument */
{
register int suc; /* success of last backchar */
if (n < 0) /* the other way...*/
return(goeop(f, -n));
while (n-- > 0) { /* for each one asked for */
/* first scan back until we are in a word */
suc = backchar(FALSE, 1);
while (!inword() && suc)
suc = backchar(FALSE, 1);
curwp->w_doto = 0; /* and go to the B-O-Line */
/* and scan back until we hit a <NL><NL> or <NL><TAB>
or a <NL><SPACE> */
while (lback(curwp->w_dotp) != curbp->b_linep)
if (llength(curwp->w_dotp) != 0 &&
lgetc(curwp->w_dotp, curwp->w_doto) != TAB &&
lgetc(curwp->w_dotp, curwp->w_doto) != ' ')
curwp->w_dotp = lback(curwp->w_dotp);
else
break;
/* and then forward until we are in a word */
if (lback(curwp->w_dotp) == curbp->b_linep)
suc = (curwp->w_dotp != curbp->b_linep);
else
suc = forwchar(FALSE, 1);
while (suc && !inword())
suc = forwchar(FALSE, 1);
}
curwp->w_flag |= WFMOVE; /* force screen update */
return(TRUE);
}
goeop(f, n) /* go forword to the end of the current paragraph
here we look for a <NL><NL> or <NL><TAB> or <NL><SPACE>
combination to delimit the beginning of a paragraph */
int f, n; /* default Flag & Numeric argument */
{
register int suc; /* success of last backchar */
if (n < 0) /* the other way...*/
return(gobop(f, -n));
while (n-- > 0) { /* for each one asked for */
/* first scan forward until we are in a word */
suc = TRUE; /* forwchar(FALSE, 1); */
while (!inword() && suc)
suc = forwchar(FALSE, 1);
curwp->w_doto = 0; /* and go to the B-O-Line */
if (suc) /* of next line if not at EOF */
curwp->w_dotp = lforw(curwp->w_dotp);
/* and scan forword until we hit a <NL><NL> or <NL><TAB>
or a <NL><SPACE> */
while (curwp->w_dotp != curbp->b_linep) {
if (llength(curwp->w_dotp) != 0 &&
lgetc(curwp->w_dotp, curwp->w_doto) != TAB &&
lgetc(curwp->w_dotp, curwp->w_doto) != ' ')
curwp->w_dotp = lforw(curwp->w_dotp);
else
break;
}
/* and then backward until we are in a word */
suc = backchar(FALSE, 1);
while (suc && !inword()) {
suc = backchar(FALSE, 1);
}
curwp->w_doto = llength(curwp->w_dotp); /* and to the EOL */
}
curwp->w_flag |= WFMOVE; /* force screen update */
return(TRUE);
}
#endif
/*
* This routine, given a pointer to a LINE, and the current cursor goal
* column, return the best choice for the offset. The offset is returned.
* Used by "C-N" and "C-P".
*/
getgoal(dlp)
register LINE *dlp;
{
register int c;
register int col;
register int newcol;
register int dbo;
col = 0;
dbo = 0;
while (dbo != llength(dlp)) {
c = lgetc(dlp, dbo);
newcol = col;
if (c == '\t')
newcol += tabsize - (newcol % tabsize) - 1;
else if ((c&0x7F) < 0x20 || (c&0x7F) == 0x7F)
++newcol;
++newcol;
if (newcol > curgoal)
break;
col = newcol;
++dbo;
}
return (dbo);
}
/*
* Scroll forward by a specified number of lines, or by a full page if no
* argument. Bound to "C-V". The "2" in the arithmetic on the window size is
* the overlap; this value is the default overlap value in ITS EMACS. Because
* this zaps the top line in the display window, we have to do a hard update.
*/
forwpage(f, n)
register int n;
{
register LINE *lp, *dp;
if (f == FALSE) {
n = curwp->w_ntrows - 2; /* Default scroll. */
if (n <= 0) /* Forget the overlap */
n = 1; /* if tiny window. */
} else if (n < 0)
return (backpage(f, -n));
#if CVMVAS
else /* Convert from pages */
n *= curwp->w_ntrows; /* to lines. */
#endif
lp = curwp->w_linep;
dp = curwp->w_dotp;
while (n > 0 && dp != curbp->b_linep)
{--n; lp = lforw(lp); dp = lforw(dp);}
curwp->w_linep = lp;
curwp->w_dotp = dp;
curwp->w_doto = 0;
curwp->w_flag |= WFHARD;
return (TRUE);
}
/*
* This command is like "forwpage", but it goes backwards. The "2", like
* above, is the overlap between the two windows. The value is from the ITS
* EMACS manual. Bound to "M-V". We do a hard update for exactly the same
* reason.
*/
backpage(f, n)
register int n;
{
register LINE *lp, *dp;
if (f == FALSE) {
n = curwp->w_ntrows - 2; /* Default scroll. */
if (n <= 0) /* Don't blow up if the */
n = 1; /* window is tiny. */
} else if (n < 0)
return (forwpage(f, -n));
#if CVMVAS
else /* Convert from pages */
n *= curwp->w_ntrows; /* to lines. */
#endif
lp = curwp->w_linep;
dp = curwp->w_dotp;
while (n > 0 && lback(lp) != curbp->b_linep)
{--n; lp = lback(lp); dp = lback(dp);}
while (n > 0 && lback(dp) != curbp->b_linep)
{--n; dp = lback(dp);}
curwp->w_linep = lp;
curwp->w_dotp = dp;
curwp->w_doto = 0;
curwp->w_flag |= WFHARD;
return (TRUE);
}
/*
* Set the mark in the current window to the value of "." in the window. No
* errors are possible. Bound to "M-.".
*/
setmark(f, n)
{
curwp->w_markp = curwp->w_dotp;
curwp->w_marko = curwp->w_doto;
mlwrite("[Mark set]");
return (TRUE);
}
/*
* Clear the mark in the current window. No errors are possible.
* Bound to ^X <space>
*/
remmark(f, n)
{
curwp->w_markp = NULL;
curwp->w_marko = 0;
mlwrite("[Mark removed]");
return (TRUE);
}
/*
* Swap the values of "." and "mark" in the current window. This is pretty
* easy, bacause all of the hard work gets done by the standard routine
* that moves the mark about. The only possible error is "no mark". Bound to
* "C-X C-X".
*/
swapmark(f, n)
{
register LINE *odotp;
register int odoto;
if (curwp->w_markp == NULL) {
mlwrite("No mark in this window");
return (FALSE);
}
odotp = curwp->w_dotp;
odoto = curwp->w_doto;
curwp->w_dotp = curwp->w_markp;
curwp->w_doto = curwp->w_marko;
curwp->w_markp = odotp;
curwp->w_marko = odoto;
curwp->w_flag |= WFMOVE;
return (TRUE);
}
#if DECEDT
int advset = TRUE;
/* advance command. sets advance flag true */
advadv(f, n)
{
advset = TRUE;
return(TRUE);
}
/* backup command. sets backup flag false */
advback(f, n)
{
advset = FALSE;
return(TRUE);
}
/* bottom command. goes to top or bottom of buffer */
advbot(f, n)
{
return( (advset == TRUE)? goeob(f, n): gobob(f, n) );
}
/* character command. goes forward or backward a character */
advchar(f, n)
{
return( (advset == TRUE)? forwchar(f, n): backchar(f, n) );
}
/* word command. goes forward or backward a word */
advword(f, n)
{
return( (advset == TRUE)? forwword(f, n): backword(f, n) );
}
/* line command. goes to beginning of next or previous line */
advline(f, n)
{
int stat;
if (advset != TRUE && curwp->w_doto > 0) stat = TRUE;
else stat = ((advset == TRUE)? scdnwind(f, n): scupwind(f, n));
thisflag &= ~CFCPCN;
return( (stat == TRUE)? gobol(f, n): stat);
}
/* end of line command. goes to end of next or previous line */
adveol(f, n)
{
int stat;
if (advset == TRUE && curwp->w_doto < llength(curwp->w_dotp)) stat = TRUE;
else stat = ((advset == TRUE)? forwline(f, n): backline(f, n));
thisflag &= ~CFCPCN;
return( (stat == TRUE)? goeol(f, n): stat);
}
/* search command. searches forward or reverse */
advsearch(f, n)
{
return( (advset == TRUE)? forwsearch(f, n): backsearch(f, n) );
}
/* hunt command. hunts forward or reverse */
advhunt(f, n)
{
return( (advset == TRUE)? forwhunt(f, n): backhunt(f, n) );
}
/* smooth next page command. goes forward page */
scnxpage(f, n)
{
#if 1
int s, adv;
/* EDT-like paging */
gobol(f, n);
if (f == FALSE) n = 1;
n *= (curwp->w_ntrows * 2 + 1) / 3;
if (isvt100) {
s = TRUE;
adv = (n >= 0);
if (!adv) n = -n;
while (n-- > 0 && s == TRUE) {
s = (adv? scdnwind(TRUE, 1): scupwind(TRUE, 1) );
if (s == TRUE && n > 0) update(HOOK);
}
}
else
s = scdnwind(TRUE, n);
thisflag &= ~CFCPCN;
return(s);
#else
/* Emacs-like paging */
return(forwpage(f, n));
#endif
}
/* smooth previous page command. goes backward page */
scprpage(f, n)
{
if (f == FALSE) { f = TRUE; n = 1; }
return( scnxpage(f, -n) );
}
/* page command. goes forward or backward a page */
advpage(f, n)
{
return( (advset == TRUE)? scnxpage(f, n): scprpage(f, n) );
}
/*
* Special insertion. The argument is the ascii value of the character
* to insert into the buffer. All the characters
* are taken literally, with the exception of the newline, which always has
* its line splitting meaning.
*/
specins(f, n)
{
if (curbp->b_mode&MDVIEW) /* don't allow this command if */
return(rdonly()); /* we are in read only mode */
n = ((f == TRUE)? (n & 0xFF): 0);
return( (n == '\n')? lnewline(): linsert(1, n) );
}
/*
* Undelete the last deleted character.
*/
yankchar(f, n)
{
int s;
if (curbp->b_mode&MDVIEW) /* don't allow this command if */
return(rdonly()); /* we are in read only mode */
if (ykchar == -1 || n <= 0) s = FALSE;
else if (ykchar == '\n') {
s = TRUE;
while (s == TRUE && n-- > 0) s = lnewline();
}
else s = linsert(n, ykchar);
return(s);
}
/*
* Octal insertion.
* Quote next character and insert in C backslash octal format.
* Unbound
*/
octalins(f, n)
{
register int s;
register int c;
int i, len;
char oct[10];
if (curbp->b_mode&MDVIEW) /* don't allow this command if */
return(rdonly()); /* we are in read only mode */
mlwrite(": character to insert ");
c = tgetc() & 0xFF;
len = 0;
while (c > 0) {
oct[len++] = '0' + c % 8;
c /= 8;
}
while (len < 3) oct[len++] = '0';
s = TRUE;
while (n-- > 0 && s == TRUE) {
linsert(1, '\\');
i = len;
while(i > 0) s = linsert(1, oct[--i]);
}
return(s);
}
/* null commnad. does nothing */
nullcmd(f, n)
{
return(TRUE);
}
#endif